package com.yangjun.service.report;

import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yangjun.common.ServerResponse;
import com.yangjun.common.comparator.TargetItemComparator;
import com.yangjun.common.comparator.TargetItemComparatorByTargetArr;
import com.yangjun.common.enums.report.ReportTemplateTypeEnum;
import com.yangjun.common.enums.report.ReportTypeEnum;
import com.yangjun.common.excel.DataBaseExcelContext;
import com.yangjun.common.excel.ExcelExportResult;
import com.yangjun.dao.mybatis.mapper.report.InventoryReportExportMapper;
import com.yangjun.dao.mybatis.mapper.report.ReportDownloadStatusMapper;
import com.yangjun.dao.mybatis.mapper.report.ReportExportStatusMapper;
import com.yangjun.entity.report.DvExcelFieldDefinitionEntity;
import com.yangjun.entity.report.DvReportDownloadStatusEntity;
import com.yangjun.entity.report.DvReportExportStatus;
import com.yangjun.entity.report.DwInventoryEntity;
import com.yangjun.po.report.InventoryReportExportPO;
import com.yangjun.service.permission.ReportExportPermissionService;
import com.yangjun.utils.DvDateUtils;
import com.yangjun.utils.DvUtils;
import com.yangjun.vo.report.InventoryReportExportVO;
import com.yangjun.vo.report.InventoryReportManageVO;
@Service
public class InventoryReprotExportService  {
	@Value("${excel.uploadPath}")
    private String uploadPath;
	@Value("${excel.downloadPath}")
    private String downloadPath;
	
	@Autowired
	private DataBaseExcelContext context;
	@Autowired
	private InventoryReportExportMapper inventoryReportExportMapper;
	@Autowired
	private ReportExportStatusMapper reportExportStatusMapper;
	@Autowired
	private ReportDownloadStatusMapper reportDownloadStatusMapper;
	@Autowired
	private ReportCommonService reportCommonService;
	@Autowired
	private ReportExportPermissionService reportExportPermissionService;
	//报表类型
	private final static String reporttype = "inventory";
	//数据类型默认顺序
	private final static String[] dataTypeId = new String[]{"purchInstock","purchReturn","storeInstock","outstock","oqcReturn","qcOut","pqcReturn","qcWsout"};
	//搜索模板
	private final static String[] inventoryTemplate =new String[]{"wareCode","manufacturer","providername"};
	//查询数据类型
	private List<Map<String,Object>> queryDataType(String selectDataType){
		List<Map<String,Object>> resultList = Lists.newArrayList();
		Map<String,String>  categoryMap = reportCommonService.queryCategory(reporttype);
		for(String dataType : dataTypeId){
			Map<String,Object> item = Maps.newHashMap();
			String dataTypeName = categoryMap.get(dataType).toString();
			item.put("name", dataTypeName);
			item.put("value", dataType);
			if(dataType.equals(selectDataType)){
				item.put("selected", true);
			}else{
				item.put("selected", false);
			}
			resultList.add(item);
		}
		return resultList;
	}
	private String getDataTypeName(String dataType){
		Map<String,String>  categoryMap = reportCommonService.queryCategory(reporttype);
		return categoryMap.get(dataType).toString();
	}
	//获取生产厂家列表
	public Object getManufacturer(){
		return ServerResponse.createBySuccess(inventoryReportExportMapper.queryManufacturer());
	}
	//获取供应商列表
	public Object getProvider(){
		return ServerResponse.createBySuccess(inventoryReportExportMapper.queryProvider());
	}
	/**
	 * @Description 获取维度信息
	 * @return
	 * @author yangjun
	 * @Date 2017年7月5日 上午11:50:06
	 */
	//fetchType(取数类型) : 临时(temporary)订阅(subscription)
	public Object getDeminsion(String reportid,String userid){
		InventoryReportExportVO itreVO = null;
		DvReportExportStatus dvReportExportStatus = reportExportStatusMapper.queryReportStatusByReportId(reportid);
		
		String reportName = "进销存-";
		String batchno = "";
		//默认按商品编码搜索
		String searchName = "wareCode";
		String searchValue = "";
		//取数类型(默认临时取数)
		String fetchType = ReportTypeEnum.temporary.getValue();
		//数据类型
		String dataType = "purchInstock";
		
		//查询开始时间(默认都是1年前的昨天)
		String beginDate = DvDateUtils.getYesterDayOfLastYear();
		//查询结束时间(默认都是昨天)
		String endDate = DvDateUtils.getDate(new Date(), -1);
		//选择的指标
		String[] targetSelectData  = null;

		if(dvReportExportStatus!=null){
			itreVO = JSON.parseObject(dvReportExportStatus.getReportparam(), InventoryReportExportVO.class);
			targetSelectData = itreVO.getTarget();
			reportName = itreVO.getReportName();
			fetchType = itreVO.getFetchType();
			dataType = itreVO.getDataType();
			beginDate = itreVO.getBeginDate();
			endDate = itreVO.getEndDate();
			searchName = itreVO.getSearchName();
			searchValue = itreVO.getSearchValue().length>0?StringUtils.join(itreVO.getSearchValue(),","):"";
		}
		Map<String,Object> demensionMap = Maps.newHashMap();
		//取数类型
		demensionMap.put("fetchType",fetchType);
		//数据类型
		demensionMap.put("dataType",queryDataType(dataType));
		//商品批号
		demensionMap.put("batchno",batchno);
		//查询日期
		demensionMap.put("dateMethod", queryDateMethod(beginDate,endDate));
		//报表名
		demensionMap.put("reportName",reportName);
		//报表类型
		demensionMap.put("reporttype", reporttype);
		//选择的指标
		demensionMap.put("selectTarget",targetSelectData==null?"":StringUtils.join(targetSelectData,","));
		demensionMap.put("searchName", searchName);
		demensionMap.put("searchValue", searchValue);
		//更新时间
		demensionMap.put("update", "每天 9:00 AM");
		
		reportCommonService.deleteUploadReport(userid);
		return ServerResponse.createBySuccess(demensionMap);
	}
	public Object querySearch(String dataType,String searchName){
		if("purchInstock".equals(dataType)||"purchReturn".equals(dataType)){
			return ServerResponse.createBySuccess(reportCommonService.getSearchTemplate(inventoryTemplate,searchName));
		}else{
			return ServerResponse.createBySuccess(reportCommonService.getSearchTemplate(Arrays.copyOfRange(inventoryTemplate,0,2),searchName));
		}
	}
	public Object queryTarget(String userid,String dataType,String[] targetSelectData){
		Map<String,Object> demensionMap = Maps.newHashMap();
		//修改报表排序号的字段顺序
		List<Map<String,Object>> sortTargetSelectData=Lists.newArrayList();
		//获取每个报表的指标分类
		List<DvExcelFieldDefinitionEntity> excelFieldDefinitionList = reportCommonService.getExcelFieldDefinitionList(reporttype,dataType);
		Map<String,String> tmpCategoryMap = reportCommonService.queryCategory(reporttype);
		Map<String,String> categoryMap = Maps.newHashMap();
		categoryMap.put("name", dataType);
		categoryMap.put("value", tmpCategoryMap.get(dataType).toString());
		List<Map<String,Object>> targetList = Lists.newArrayList();
		demensionMap.put("category", categoryMap);
		//查询有权限显示的报表字段
		String[] allowFieldArr = reportExportPermissionService.getReportAllowField(userid, reporttype);
		if(allowFieldArr!=null&&allowFieldArr.length>0){
			for(DvExcelFieldDefinitionEntity excelFieldDefinitionEntity : excelFieldDefinitionList){
				//权限控制能够显示的字段，如果查询不到对应角色的权限直接不显示字段。
				//&&("18".equals(userid)||"507".equals(userid)||"715".equals(userid)||"6".equals(userid)||"518".equals(userid)||"141".equals(userid)||"481".equals(userid))
				if(allowFieldArr!=null){
					List<String> allowFieldList = Arrays.asList(allowFieldArr);
					if(!allowFieldList.contains(excelFieldDefinitionEntity.getEntityName())){
						continue;
					}
				}
				//封装默认的指标格式
				String categoryId = excelFieldDefinitionEntity.getCategoryId();
				if(StringUtils.isNotBlank(categoryId)){
					String entityName = excelFieldDefinitionEntity.getEntityName();
					String title = excelFieldDefinitionEntity.getTitle();
					int sort = excelFieldDefinitionEntity.getFieldSort();
					Map<String,Object> itemMap = Maps.newHashMap();
					itemMap.put("value", entityName);
					itemMap.put("name", title);
					itemMap.put("sort", sort);
					itemMap.put("checked", false);
					if(targetSelectData!=null){
						for(int i=0,len=targetSelectData.length;i<len;i++){
							if(entityName.equals(targetSelectData[i])){
								itemMap.put("checked", true);
								//修改报表排序号的字段顺序
								sortTargetSelectData.add(itemMap);
							}
						}					
					}
					//已经在上面初始化了不用判断空
					targetList.add(itemMap);
				}
			}
			//根据数据库给定的sort字段进行排序
			Collections.sort(targetList,new TargetItemComparator());
		}
		//指标
		demensionMap.put("target", targetList);
		Collections.sort(sortTargetSelectData, new TargetItemComparatorByTargetArr(targetSelectData));
		demensionMap.put("sortTarget", sortTargetSelectData);
		return ServerResponse.createBySuccess(demensionMap);
	}
	
	private Object queryDateMethod(String beginDate,String endDate){
		//summaryCycle(汇总周期) : naturalDay(自然天)naturalWeek(自然周)naturalMonth(自然月)custom(自定义)
		Map<String,Object> resultMap = Maps.newHashMap();
		String[] fetchTypeArr = {"temporary","subscription"};
		for(String fetchTypeItem : fetchTypeArr ){
			if("temporary".equals(fetchTypeItem)){
				//临时取数
				resultMap.put(fetchTypeItem, queryDateOfTemporaryWay(beginDate,endDate));
			}else if("subscription".equals(fetchTypeItem)){
				//订阅报表
				resultMap.put(fetchTypeItem, queryDateOfSubscriptionWay(beginDate,endDate));
			}
		}
		return resultMap;
	}
	private Map<String,Object> queryDateOfTemporaryWay(String beginDate,String endDate){
		Map<String,Object> temporaryDate = Maps.newHashMap();
		//开始时间
		temporaryDate.put("beginDate", beginDate);
		//结束时间
		temporaryDate.put("endDate", endDate);
		return temporaryDate;
	}
	private Map<String,String> queryDateOfSubscriptionWay(String beginDate,String endDate){
		Map<String,String> subscriptionDate = Maps.newHashMap();
		subscriptionDate.put("name","近一年");
		subscriptionDate.put("beginDate",beginDate);
		subscriptionDate.put("endDate",endDate);
		return subscriptionDate;
	}
	
	
	public Object queryData(String reportid){
		DvReportExportStatus dvReportExportStatus = reportExportStatusMapper.queryReportStatusByReportId(reportid);
		InventoryReportExportVO itreVO = JSON.parseObject(dvReportExportStatus.getReportparam(), InventoryReportExportVO.class);
		return queryData(itreVO);
	}
	public Object queryData(InventoryReportExportVO itreVO){
		InventoryReportExportPO itrePo= new InventoryReportExportPO();
		
		Map<String,Object> resultMap = Maps.newHashMap();
		String[] targetArr = itreVO.getTarget();
		List<String> targetList = Arrays.asList(targetArr);
		
		Long start = System.currentTimeMillis();
		List<DvExcelFieldDefinitionEntity>  reportFieldDefinition= reportCommonService.getExcelFieldDefinitionList(reporttype);
		//装载表格数据
		List<List<String>> tableList = Lists.newArrayList();

		List<String> titleList = Lists.newArrayList();
		for(String item : targetList){
			for(DvExcelFieldDefinitionEntity definition : reportFieldDefinition){
				String name = definition.getEntityName();
				if(item.equals(name)){
					titleList.add(definition.getTitle());
				}
			}
		}
		tableList.add(titleList);
		System.out.println("1."+(System.currentTimeMillis()-start)/1000);
		if(itreVO.getSearchValue().length>0){
			itreVO.setSearchValue(itreVO.getSearchValue());
		}else{
			itreVO.setSearchValue(null);
		}
		System.out.println("2."+(System.currentTimeMillis()-start)/1000);
		BeanUtils.copyProperties(itreVO, itrePo);
		//根据权限进行查询或者下载，单品分析页面要判断用户是否是属于商品经理订阅的报表，如果是对应的商品经理只能下载所管理的商品否则可以下载全部商品根据(0是1不是-1找不到角色，有问题可咨询庄曼娜李建华)
		List<DwInventoryEntity> list = inventoryReportExportMapper.queryData(itrePo, 1, 10);
		System.out.println("单品分析查询数据 list:"+list.size());
		JSONArray objectArr = JSON.parseArray(JSONObject.toJSONString(list));
		for(int i = 0,len = objectArr.size() ; i<len ; i++){
			JSONObject object = objectArr.getJSONObject(i);
			List<String> itemList = Lists.newArrayList();
			for(String item : targetList){
				itemList.add(object.getString(item)==null?"":object.getString(item));
			}
			tableList.add(itemList);
		}
		System.out.println("3."+(System.currentTimeMillis()-start)/1000);
		resultMap.put("tableData",tableList );
		resultMap.put("rownum",list.size()>0?list.get(0).getCountNum():0);
		return ServerResponse.createBySuccess(resultMap);
	}
	

	public Object addOrUpdateReport(InventoryReportExportVO itreVO){
		String reportid = itreVO.getReportid();
		List<String> targetNameList = Lists.newArrayList();
		String[] targetArr = itreVO.getTarget();

		List<DvExcelFieldDefinitionEntity> excelFieldDefinitionList = reportCommonService.getExcelFieldDefinitionList(reporttype);
		for(String target : targetArr){
			for(DvExcelFieldDefinitionEntity dvExcelFieldDefinitionItem : excelFieldDefinitionList){
				String entityName = dvExcelFieldDefinitionItem.getEntityName();
				String targetName = dvExcelFieldDefinitionItem.getTitle();
					if(target.equals(entityName)){
						targetNameList.add(targetName);
					}
			}
		}
		InventoryReportManageVO inventoryReportManageVO = new InventoryReportManageVO();
		BeanUtils.copyProperties(itreVO, inventoryReportManageVO);
		inventoryReportManageVO.setReportid(reportid);
		//权限修改了平台ID,对应的平台名称也要变
		inventoryReportManageVO.setTargetName(targetNameList);
		inventoryReportManageVO.setDataType(getDataTypeName(itreVO.getDataType()));
		inventoryReportManageVO.setSearchName(ReportTemplateTypeEnum.getTemplateName(itreVO.getSearchName()));
		inventoryReportManageVO.setSaveTime(DvDateUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss"));
		String[] searchArr = itreVO.getSearchValue();
		if(searchArr!=null&&searchArr.length>0){
			inventoryReportManageVO.setSearchValue(StringUtils.join(searchArr,","));
		}

		if(StringUtils.isNotBlank(reportid)){
			DvReportExportStatus dvReportExportStatus = new DvReportExportStatus();
			dvReportExportStatus.setReportid(reportid);
			dvReportExportStatus.setReportName(itreVO.getReportName());
			dvReportExportStatus.setReportparam(JSON.toJSONString(itreVO));
			dvReportExportStatus.setReportManageParam(JSON.toJSONString(inventoryReportManageVO));
			if(reportExportStatusMapper.updateReportStatus(dvReportExportStatus)>0){
				return ServerResponse.createBySuccessMessage("修改报表成功!");
			}else{
				return ServerResponse.createBySuccessMessage("修改报表失败!");
			}
		}else{
			//加入报表前需要根据用户ID，报表名去判断是否有重名的报表
			if(reportExportStatusMapper.queryReport(itreVO.getUserid(), itreVO.getReportName())>0){
				return ServerResponse.createByErrorMessage("已存在相同名称的报表，请重新命名!");
			}else{
				reportid = reporttype+String.valueOf(System.currentTimeMillis())+String.valueOf((int)((Math.random()*9+1)*100000));
				itreVO.setReportid(reportid);
				inventoryReportManageVO.setReportid(reportid);
				DvReportExportStatus dvReportExportStatus = new DvReportExportStatus();
				BeanUtils.copyProperties(itreVO, dvReportExportStatus);
				dvReportExportStatus.setCreatetime(new Date());
				dvReportExportStatus.setReportparam(JSON.toJSONString(itreVO));
				dvReportExportStatus.setReportManageParam(JSON.toJSONString(inventoryReportManageVO));
				dvReportExportStatus.setReporttype(reporttype);
				dvReportExportStatus.setFileName(itreVO.getUploadFileId()+itreVO.getUploadFileName());
				if(reportExportStatusMapper.insertReportStatus(dvReportExportStatus)>0){
					return ServerResponse.createBySuccessMessage("添加报表成功!");
				}else{
					return ServerResponse.createByErrorMessage("添加报表失败!");
				}
			}
		}
	}
	

	public Object download(InventoryReportExportVO itreVo,HttpServletRequest request){
		context.initDBExcelDefinitionReader("export");
		InventoryReportExportPO itrePo= new InventoryReportExportPO();
		String[] targetArr = itreVo.getTarget();
		List<String> targetList = Arrays.asList(targetArr);
		
		if(itreVo.getSearchValue().length>0){
			itreVo.setSearchValue(itreVo.getSearchValue());
		}else{
			itreVo.setSearchValue(null);
		}
		BeanUtils.copyProperties(itreVo, itrePo);
		//用户ID，UUID组成下载ID
		String downloadId = itreVo.getUserid()+UUID.randomUUID().toString().replaceAll("-", "");
		String downloadReportName = itreVo.getReportName();
		String fileName =downloadId+downloadReportName+".xlsx";
		int rownum = inventoryReportExportMapper.queryCount(itrePo);
		System.out.println(rownum);
		DvReportDownloadStatusEntity dvReportDownloadStatusEntity = new DvReportDownloadStatusEntity();
		dvReportDownloadStatusEntity.setDownloadId(downloadId);
		dvReportDownloadStatusEntity.setFileName(fileName);
		dvReportDownloadStatusEntity.setReportName(downloadReportName);
		dvReportDownloadStatusEntity.setReportType(reporttype);
		dvReportDownloadStatusEntity.setUserid(itreVo.getUserid());
		dvReportDownloadStatusEntity.setUsername(itreVo.getUsername());
		dvReportDownloadStatusEntity.setUserrealname(itreVo.getUserrealname());
		dvReportDownloadStatusEntity.setTargetName(JSON.toJSONString(reportCommonService.getTargetNameList(targetArr, reporttype)));
		dvReportDownloadStatusEntity.setIp(DvUtils.getIp(request));
		if(reportDownloadStatusMapper.insertReport(dvReportDownloadStatusEntity)>0){
			DownloadTask downloadTask = new DownloadTask(fileName,targetList,rownum,itrePo,dvReportDownloadStatusEntity);
			new Thread(downloadTask).start();  
			return ServerResponse.createBySuccessMessage("加入下载列表成功！");
		}else{
			return ServerResponse.createByErrorMessage("加入下载列表失败！");
		}
	}
	public Object addDownloadTask(String reportid,HttpServletRequest request){
		DvReportExportStatus dvReportExportStatus = reportExportStatusMapper.queryReportStatusByReportId(reportid);
		InventoryReportExportVO itreVo = JSON.parseObject(dvReportExportStatus.getReportparam(), InventoryReportExportVO.class);
		return download(itreVo,request);
	}
	public Object addDownloadTask(InventoryReportExportVO itreVo,HttpServletRequest request){
		if(reportDownloadStatusMapper.queryReportByName(itreVo.getUserid(), itreVo.getReportName())>0){
			return ServerResponse.createByErrorMessage("已存在相同名称的报表，请重新命名!");
		}else{
			return download(itreVo,request);
		}
	}
	
	class DownloadTask implements Runnable{
		public  boolean flag = true;
		private String fileName;
		private Integer rownum;
		private List<String> targetList;
		private InventoryReportExportPO itrePo;
		private DvReportDownloadStatusEntity dvReportDownloadStatusEntity;
		public DownloadTask(String fileName,List<String> targetList,int rownum,InventoryReportExportPO itrePo,DvReportDownloadStatusEntity dvReportDownloadStatusEntity){
			this.fileName = fileName;
			this.rownum = rownum;
			this.targetList = targetList;
			this.itrePo = itrePo;
			this.dvReportDownloadStatusEntity = dvReportDownloadStatusEntity;
		}
		public void stopThread(){
			flag = false;
		}
		@Override
		public void run() {
			while (flag){
				OutputStream ops = null;
				ExcelExportResult exportResult = null;
				try {
					ops = new FileOutputStream(downloadPath+fileName);
					System.out.println("targetList:"+targetList.size());
					exportResult = context.createEmptyExcelForPart(reporttype,DwInventoryEntity.class,targetList);
					int pageSize = 40000;
					int totalPage = (int)Math.ceil(rownum/pageSize);
					totalPage += rownum%pageSize>0?1:0; 
					for(int i=1;i<=totalPage;i++){
						exportResult.append(inventoryReportExportMapper.queryData(itrePo, i, pageSize));
					}
					
				Workbook workbook = exportResult.build();
				workbook.write(ops);
				ops.close();
				workbook.close();
				dvReportDownloadStatusEntity.setEndDate(new Date());
				dvReportDownloadStatusEntity.setTimeConsume(Math.round(dvReportDownloadStatusEntity.getEndDate().getTime()-dvReportDownloadStatusEntity.getBeginDate().getTime())/1000);
				dvReportDownloadStatusEntity.setDownloadFlag(1);
				reportDownloadStatusMapper.updateReportById(dvReportDownloadStatusEntity);
				
				this.stopThread();
				} catch (Exception e) {
					System.out.println("InventoryReprot awaitTermination interrupted: " + e);  
					this.stopThread();
				}
			}
		}
	}
}
